class Observer{
  constructor(data){
    this.observe(data) //对对象添加数据劫持
  }

  observe(data){
    if(data && typeof data === 'object'){
      Object.keys(data).forEach(key=>{
        this.defineReactive(data,key,data[key])
      })
    }
  }

  defineReactive(obj,key,val){
    this.observe(val)
    const dep = new Dep()
    Object.defineProperty(obj,key,{
      enumerable:true,//是否可遍历
      configurable:false,//是否可更改编写
      get(){
        //添加订阅者
        Dep.target && dep.addSubs(Dep.target)
        return val
      },
      set:(newval)=>{
        this.observe(newval) //新对象也要走一变属性检查，然后劫持他的get和set
        if(newval != val){
          val = newval
          dep.notify()
        }
      }
    })
  }
}

class Dep{
  constructor(){
    this.subs = []
  }
  //添加订阅者
  addSubs(watcher){
    this.subs.push(watcher)
  }
  //订阅者触发更新
  notify(){
    this.subs.forEach((w)=>{
      w.update()
    })
  }
}

class Watcher{
  constructor(vm,expr,cb){
    this.vm = vm
    this.expr = expr
    this.cb = cb
    this.oldVal = this.getOldVal()//保存旧值
  }
  update(){
    const newVal = complieUtil.getVal(this.expr,this.vm)
    if(newVal !== this.oldVal)
    {
      this.cb(newVal)
    }
  }
  getOldVal(){
    Dep.target = this
    const oldVal = complieUtil.getVal(this.expr,this.vm)
    Dep.target = null
    return oldVal
  }
}